#include "flapp_peripheral.h"
#include "flapp_net_slm.h"
#include "flapp_clock.h"
#include "fldrv_board.h"
#include "flapp_display.h"
#include "fldrv_ertc.h"

typedef struct 
{			
	u8 u8SendFlag;	//语言发送标志											
	u8 u8SendCnt;		//语言播报次数
	u8 u8MedAla;		//服用提醒标志，如果在服用报警中霍尔检查才生效
	u8 u8SendDatBuf[2];		
	confirm_state bCheckVis;	//随访按键一分钟生效一次	
	u32 u32CheckVisTmr;	//随访按键一分钟生效一次	
}flapp_peripheral_para_t;	//通讯获取到的参数存储，有需要就获取
flapp_peripheral_para_t peripheral_para;

flapp_sys_para_t sys_para;

void flapp_device_power_on(void)
{
	EN_SYS_POW_ON;
	EN_MO_POW_ON;
	sys_para.bPowOnOff = ON;
	sys_para.u8PowOffCountDown = FALSE;
	peripheral_para.u8MedAla = FALSE;
	flapp_set_play_command(VOICE_POW_ON,PLAY_ONCE);
	fldrv_ertc_alarm_value_set(ALARM_TIME);
	flapp_power_on_net_init();
}

void flapp_device_power_off(void)
{
	flapp_offline_save_med_log();	//关机保存服药记录
	sys_para.bTestMode = FALSE;
	sys_para.bPowOnOff = OFF;
	sys_para.u8PowOffCountDown = COUNT_DOWN_DEFAULT;
	flapp_set_play_command(VOICE_POW_OFF,PLAY_ONCE);
	COM_PRINTF("press key power off");
}
/**
	* @brief  扫描按键
	* @param  void
  * @retval 按下键
  */
static u8 fldrv_scav_key()
{
	u8 key_num = 0;
	u8 ret_key_val = 0;
	
	if(RD_POW_KEY == KEY_PRESS)		{key_num++;ret_key_val = KEY_POWER_SHORT;}
	if(RD_VISIT_IN == KEY_PRESS)	{key_num++;ret_key_val = KEY_VISIT_SHORT;}
	if(RD_VOL_ADD == KEY_PRESS)		{key_num++;ret_key_val = KEY_VOL_ADD_SHORT;}
	if(RD_VOL_SUB == KEY_PRESS)		{key_num++;ret_key_val = KEY_VOL_SUB_SHORT;}
	if(key_num == KEY_NUM_ONE)	//单键
	{
		return ret_key_val;
	}
	else if(key_num >= KEY_NUM_INVALID)	//多键组合键
	{
		return KEY_NUM_INVALID;
	}
	return KEY_NUM_NULL;
}
/**
	* @brief  将读到按下的按键转换成键值输出
	* @param  void
  * @retval 键值
  */
static u8 fldrv_read_key_value()
{
	u8 key_val;
	static u8 key_tmr = FALSE;
	static u8 key_vaild = TRUE;
	static u8 last_key_val = FALSE;
	key_val = fldrv_scav_key();
	if(key_val == KEY_NUM_INVALID){
		key_tmr = FALSE;
		return KEY_NULL;
	}
	
	if(key_val){
		if(key_vaild)
		{
			key_tmr++;
			last_key_val = key_val;
			if(key_tmr >= KEY_LONG_TMR)
			{
				key_tmr = FALSE;
				key_vaild = FALSE;
				return key_val + 1;
			}
		}
	}
	else{
		if(key_tmr > KEY_SHORT_TMR)
		{
			key_tmr = FALSE;
			return last_key_val;
		}
		last_key_val = FALSE;
		key_tmr = FALSE;
		key_vaild = TRUE;
	}
	return KEY_NULL;
}
/**
	* @brief  长按电源键
	* @param  void
  * @retval none
  */
static void power_key_long_press_fun()
{
	if(sys_para.bPowOnOff){
		flapp_device_power_off();
		flapp_set_http_req(API_RPT_DEV_PARA,API_KEY_POWER_OFF);
	}
	else{
		flapp_device_power_on();
		flapp_clock_power_on_init();
		COM_PRINTF("press key power on");
	}
}
/**
	* @brief  按键扫描和处理
	* @param  void
  * @retval none
  */
static void flapp_key_fun(void)
{
	u8 key_res;	
	key_res = fldrv_read_key_value();

	if((sys_para.bPowOnOff == OFF) && key_res > KEY_POWER_LONG)
		return;
	
	switch(key_res)
	{
		case KEY_POWER_SHORT:
			flapp_ertc_time_show();
			flapp_set_play_command(VOICE_KEY,PLAY_ONCE);
			break;
		case KEY_POWER_LONG:
			power_key_long_press_fun();
			break;
		case KEY_VISIT_SHORT:
			if(peripheral_para.bCheckVis == FALSE){
				flapp_set_http_req(API_CHECK_VIS,API_STATUS_MAX);
				peripheral_para.bCheckVis = TRUE;
				peripheral_para.u32CheckVisTmr = flapp_get_current_timestp();
			}
			flapp_set_play_command(VOICE_KEY,PLAY_ONCE);
			break;
		case KEY_VISIT_LONG:
			flapp_set_http_req(API_RPT_SEEK_HELP,API_STATUS_MAX);
			flapp_set_play_command(VOICE_KEY,PLAY_WTICE);
			break;
		case KEY_VOL_ADD_SHORT:
			if(sys_para.u8VolLev < VOL_DEFAULT)
				sys_para.u8VolLev++;
			flapp_set_http_req(API_RPT_VOLUMW,API_STATUS_MAX);
			flapp_set_play_command(VOICE_KEY_VOL,PLAY_ONCE);
			break;
		case KEY_VOL_SUB_SHORT:
			if(sys_para.u8VolLev > 1)
				sys_para.u8VolLev--;
			flapp_set_http_req(API_RPT_VOLUMW,API_STATUS_MAX);
			flapp_set_play_command(VOICE_KEY_VOL,PLAY_ONCE);
			break;
	}
}

/**
	* @brief  设置语音内容和播放次数
	* @param  void
  * @retval none
  */
void flapp_set_med_alarm(u8 var)
{
	peripheral_para.u8MedAla = var;
}
/**
	* @brief  设置语音内容和播放次数
	* @param  void
  * @retval none
  */
void flapp_set_play_command(u8 cmd,u8 cnt)
{
	if(RD_VOICE_BUSY && (cmd == VOICE_KEY || cmd == VOICE_KEY_VOL))			//按键声不能打断其他音频播放
			return;
	
	if(peripheral_para.u8SendFlag && (cmd == VOICE_KEY || cmd == VOICE_KEY_VOL))	//按键声不能打断其他音频发送
		return;
	
	if(sys_para.bPowOnOff == OFF && cmd != VOICE_POW_OFF)	//关机且关机不是关机音频
		return;
	
	peripheral_para.u8SendDatBuf[1] = cmd;
	peripheral_para.u8SendCnt = cnt;
//	COM_PRINTF("set_cmd:%d\r\n",peripheral_para.u8SendDatBuf[1]);
}
/**
	* @brief  处理语音内容和播放次数
	* @param  void
  * @retval none
  */
void fldrv_pro_voice_command(void)
{
	u8 busy_io;
	if(peripheral_para.u8SendCnt == FALSE)	return;
	
	busy_io = RD_VOICE_BUSY;
//	COM_PRINTF("pro_cmd1:%d    io:%d    flg:%d\r\n",peripheral_para.u8SendDatBuf[1],busy_io,peripheral_para.u8SendFlag);
	
	if((busy_io == FALSE) && (peripheral_para.u8SendFlag == FALSE))
	{
		peripheral_para.u8SendCnt--;
		peripheral_para.u8SendFlag = TRUE;
		if(peripheral_para.u8SendDatBuf[1] == VOICE_POW_ON || \
			 peripheral_para.u8SendDatBuf[1] == VOICE_NET_OK || \
			 peripheral_para.u8SendDatBuf[1] == VOICE_KEY || \
			 peripheral_para.u8SendDatBuf[1] == VOICE_POW_OFF){
			peripheral_para.u8SendDatBuf[0] = VOICE_VOL_3;
		}
		else
		{
			switch(sys_para.u8VolLev)
			{
				case VOL_LEV_0:
					peripheral_para.u8SendCnt = FALSE;
					peripheral_para.u8SendFlag = FALSE;
					peripheral_para.u8SendDatBuf[0] = 0;
					break;
				case VOL_LEV_1:
					peripheral_para.u8SendDatBuf[0] = VOICE_VOL_1;
					break;
				case VOL_LEV_2:
					peripheral_para.u8SendDatBuf[0] = VOICE_VOL_3;
					break;
				case VOL_LEV_3:
					peripheral_para.u8SendDatBuf[0] = VOICE_VOL_5;
					break;
				case VOL_LEV_4:
					peripheral_para.u8SendDatBuf[0] = VOICE_VOL_7;
					break;
				default:
					peripheral_para.u8SendDatBuf[0] = VOICE_VOL_3;
					break;
			}
		}
	}
	else
	{
		if(busy_io == FALSE)
		{
			if(peripheral_para.u8SendFlag)
				peripheral_para.u8SendFlag = FALSE;	//音频还在协议发送,毕竟协议发送也是要一点时间的
		}
	}
}
/**
	* @brief  设置音量
	* @param  void
  * @retval none
  */
void flapp_set_volume(u8 vol)
{
	sys_para.u8VolLev = vol;
}
/**
	* @brief  USB插入检测
	* @param  void
  * @retval none
  */
static void flapp_vbus_check()
{
	static u8 check_cnt = FALSE;	//USB检测计时
	if(RD_VUSB)
	{
		if(sys_para.bHaveUsb == FALSE)
			check_cnt++;
		if(check_cnt >= 3)
		{
			sys_para.bHaveUsb = TRUE;
			if((sys_para.bPowOnOff == OFF) && (sys_para.u8PowOffCountDown <= COUNT_DOWN_DEFAULT - 10))	//这里保证插电关机的时候关机音乐放完了再充电开机
			{
				EN_CHAR_ASSI_OFF;
				flapp_device_power_on();
				log_debug("power on by charge");
			}
		}
	}
	else
	{
		check_cnt = FALSE;
		if(sys_para.bHaveUsb == TRUE)
		{
			EN_CHAR_ASSI_OFF;
			sys_para.bHaveUsb = FALSE;
		}
	}
}
/**
* @brief  霍尔检测
	* @param  void
  * @retval none
  */
static void flapp_hall_check()
{
	static u8 cnt = FALSE;
	if(peripheral_para.u8MedAla == FALSE)	
		return;
	
	if(RD_HALL_IN == OFF){
		cnt = FALSE;
	}
	else{
		cnt++;
		if(cnt)
		{
			med_time_t med_time;
  
			peripheral_para.u8MedAla = FALSE;
			flapp_set_play_command(VOICE_BEST_WISH,PLAY_ONCE);				//服药语音提醒
			flapp_set_led_sta(DIS_MED,FALSE);													//服药关闭灯光
			flapp_set_http_req(API_RPT_MED_TIME,API_STATUS_MAX);			//服药添加上报记录
			med_time = flapp_get_med_para();															
			med_time.bTodMedInfo = TRUE;																	//更新服药状态为已服药
			flapp_set_med_para(med_time);	
			flapp_set_cur_med_time();
			flapp_set_led_sta(DIS_MED,0xff);
			log_debug("report med log\r\n");
		}
	}	
}
/**
	* @brief  播放语音时许
	* @param  void
  * @retval none
  */
void fldrv_send_command(void)
{
	static u8 u8WaitRes = 0;
	static u8 u8BitCnt = 0;
	static u8 u8SendHead = TRUE;	//发送头码	
	static u8 u8SendByteH = FALSE;		//发送延时计数
	static u16 u16SendDly = FALSE;		//发送延时计数	
	if(peripheral_para.u8SendFlag == FALSE)	
		return;
	
	if(u8WaitRes)
	{
		u8WaitRes++;
		if(u8WaitRes > 150)
		{
			u8WaitRes = FALSE;
			peripheral_para.u8SendFlag = FALSE;
			u8SendByteH = FALSE;
			u8SendHead = TRUE;
		}
		return;
	}
	
	if(u8SendByteH == TRUE){
		if(++u16SendDly >= 150){
			u8SendHead = TRUE;
			u8SendByteH = TRUE + 1;
			u16SendDly = FALSE;
			peripheral_para.u8SendDatBuf[0] = peripheral_para.u8SendDatBuf[1];
		}
	}
	else{
		if(u8SendHead){
			EN_VOICE_DAT_L;
			if(++u16SendDly > 50){
				u16SendDly = FALSE;
				u8SendHead = FALSE;
			}
		}
		else{
			++u16SendDly;
			if(peripheral_para.u8SendDatBuf[0] & 1){
				if(u16SendDly <= 9)				EN_VOICE_DAT_H;
				else if(u16SendDly < 11)		EN_VOICE_DAT_L;
			}
			else{
				if(u16SendDly <= 3)				EN_VOICE_DAT_H;
				else if(u16SendDly < 11)		EN_VOICE_DAT_L;
			}
			if(u16SendDly >= 12)
			{
				u8BitCnt++;
				u16SendDly = FALSE;
				peripheral_para.u8SendDatBuf[0] >>= 1;
				if(u8BitCnt >= 8)
				{
					u8BitCnt = FALSE;
					EN_VOICE_DAT_H;
					if(u8SendByteH == FALSE)	u8SendByteH = TRUE;
					else{
						u8WaitRes = TRUE;
						
					}	
				}
			}
		}
	}
}
/**
  * @brief  this function handles timer1 overflow handler.
  * @param  none
  * @retval none
  */
void TMR1_BRK_OVF_TRG_HALL_IRQHandler(void)
{
  if(tmr_interrupt_flag_get(TMR1, TMR_OVF_FLAG) != RESET)
  {
		fldrv_send_command();
    tmr_flag_clear(TMR1, TMR_OVF_FLAG);
  }
}

void fldrv_voice_tmr_init(void)
{
	/* enable tmr1 clock */
  crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
	 /* tmr1 configuration */
  /* time base configuration */
  tmr_base_init(TMR1, 99, (system_core_clock / 1000000) - 1);
  tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
	/* overflow interrupt enable */
  tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);

  nvic_irq_enable(TMR1_BRK_OVF_TRG_HALL_IRQn, 7, 0);

  /* enable tmr1 */
  tmr_counter_enable(TMR1, TRUE);
	
	sys_para.bPowOnOff = OFF;
	sys_para.u8VolLev = VOL_DEFAULT;
}

void flapp_peripheral_init(void)
{
	fldrv_board_init();
	fldrv_voice_tmr_init();
}

u8 get_sleep_flag()
{
	if(sys_para.bPowOnOff == OFF)			//关机
		return TRUE;
	if(sys_para.bTestMode)						//测试模式
		return TRUE + 1;
	if(peripheral_para.u8SendFlag)		//音频指令发送中
		return TRUE + 2;
	if(peripheral_para.u8SendCnt)			//音频播放次数还没播放完
		return TRUE + 3;
	if(flapp_get_led_run_step() != DIS_RUNNING)		//灯显走到运行状态
		return TRUE + 4;
	if(flapp_get_http_status() && (flapp_get_net_status() == NET_STA_CONNECTED_SUCC))	//网络状态好且http请求中
		return TRUE + 5;
	if(fldrv_scav_key())
		return TRUE + 6;
	if(flapp_get_led_dis_sta())	//服药灯还亮的
		return TRUE + 7;
			
	return FALSE;
}

volatile uint32_t systick_index = 0;

void system_clock_recover(void)
{
  /* enable external high-speed crystal oscillator - hext */
  crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);

  /* wait till hext is ready */
  //while(crm_hext_stable_wait() == ERROR);

  /* enable pll */
  crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);

  /* wait till pll is ready */
  while(crm_flag_get(CRM_PLL_STABLE_FLAG) == RESET);

  /* enable auto step mode */
  crm_auto_step_mode_enable(TRUE);

  /* select pll as system clock source */
  crm_sysclk_switch(CRM_SCLK_PLL);

  /* wait till pll is used as system clock source */
  while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL);
}

void flapp_enter_sleep_config()
{
	exint_init_type exint_init_struct;
	fldrv_ertc_alarm_value_set(ALARM_TIME);
  crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
	
	scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE6);	//USB插入检测
	scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE11);	//随访按键
	scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE0);	//电源键
	scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE4);	//霍尔开关
	scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE14);	//音量+
	scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE15);	//音量-
	
	exint_default_para_init(&exint_init_struct);
  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
  exint_init_struct.line_select = EXINT_LINE_0 | EXINT_LINE_11 | EXINT_LINE_14 | EXINT_LINE_15;
  exint_init_struct.line_polarity = EXINT_TRIGGER_FALLING_EDGE;	//按键做下降沿触发
  exint_init(&exint_init_struct);
	
	exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
  exint_init_struct.line_select = EXINT_LINE_4 | EXINT_LINE_6;
  exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;	//霍尔开关和USB口做上升下降沿触发
  exint_init(&exint_init_struct);
	
	nvic_irq_enable(EXINT1_0_IRQn, 0, 0);
	nvic_irq_enable(EXINT15_4_IRQn, 1, 0);
}

void flapp_wake_up_config()
{
	exint_init_type exint_init_struct;
	exint_init_struct.line_enable = FALSE;
  exint_init_struct.line_select = EXINT_LINE_0|EXINT_LINE_4|EXINT_LINE_6|EXINT_LINE_11|EXINT_LINE_14|EXINT_LINE_15;
  exint_init(&exint_init_struct);
	exint_flag_clear(EXINT_LINE_0);
	exint_flag_clear(EXINT_LINE_4);
	exint_flag_clear(EXINT_LINE_6);
	exint_flag_clear(EXINT_LINE_11);
	exint_flag_clear(EXINT_LINE_14);
	exint_flag_clear(EXINT_LINE_15);
}

void flapp_check_sleep(void)
{
	uint8_t res;
	static u8 wait_sleep = FALSE;
	uint32_t dly;
	res = get_sleep_flag();
	if(res)
	{
		wait_sleep = FALSE;
	}
	else	wait_sleep++;
	
	if(wait_sleep >= 4)
	{
		wait_sleep = FALSE;
//		COM_PRINTF("enter sleep\r\n");
		systick_index = SysTick->CTRL;
    systick_index &= ~((uint32_t)0xFFFFFFFE);

    /* disable systick */
    SysTick->CTRL &= (uint32_t)0xFFFFFFFE;
		
		flapp_enter_sleep_config();

    /* enter deep sleep mode */
    pwc_deep_sleep_mode_enter(PWC_DEEP_SLEEP_ENTER_WFI);

    /* restore systick register configuration */
    SysTick->CTRL |= systick_index;


    /* wait clock stable */
		for(dly = 0; dly < 500; dly++);
    /* wake up from deep sleep mode, congfig the system clock */
    system_clock_recover();
		flapp_wake_up_config();
//		COM_PRINTF("wake up\r\n");
	}
}

void flapp_peripheral_fun()
{
	flapp_key_fun();
	flapp_vbus_check();
	flapp_hall_check();
	fldrv_pro_voice_command();
	flapp_check_sleep();
}
/**
	* @brief  计算外设时间运行计算，关机定时，随访有效计时
	* @param  void
  * @retval none
  */
void flapp_peripheral_tmr_run(void)
{
	if(peripheral_para.bCheckVis == TRUE)
	{
		if(flapp_get_current_timestp() - peripheral_para.u32CheckVisTmr >= TIME_1_MIN - 2)
			peripheral_para.bCheckVis = FALSE;
	}


	if(sys_para.u8PowOffCountDown && (sys_para.bPowOnOff == OFF) && (sys_para.bHaveUsb == FALSE))
	{
		sys_para.u8PowOffCountDown--;
		if(sys_para.u8PowOffCountDown == FALSE)	//关机时间上报完成断电
		{
			EN_SYS_POW_OFF;
			EN_MO_POW_OFF;
		}
	}
	else
		sys_para.u8PowOffCountDown = FALSE;		//插着电，开机
}

void flapp_set_sys_para(flapp_sys_para_t para)
{
	sys_para = para;
}

flapp_sys_para_t flapp_get_sys_para(void)
{
	return sys_para;
}
